#include "FileTransferPanel.h"

#include "MainFrame.h"

#include "MsnMessenger.h"

#include "FileTransferConnection.h"

#include "FileTransferEntry.h"
#include "FileTransferManager.h"

#include "MsnSession.h"
#include "P2PConnection.h"

#include "Util.h"

#include <wx/filename.h>

#include "../resource/xpm/logo_online.xpm"


int ID_LINK_ACCEPT = wxNewId();
int ID_LINK_SAVEAS = wxNewId();
int ID_LINK_DECLINE = wxNewId();
int ID_LINK_CANCEL = wxNewId();
int ID_LINK_OPEN = wxNewId();
int ID_LINK_REMOVE = wxNewId();


BEGIN_EVENT_TABLE(FileTransferBar, wxPanel)
	EVT_HYPERLINK(ID_LINK_ACCEPT, FileTransferBar::OnAccept)
	EVT_HYPERLINK(ID_LINK_SAVEAS, FileTransferBar::OnSaveas) 
	EVT_HYPERLINK(ID_LINK_DECLINE, FileTransferBar::OnDecline) 

	EVT_HYPERLINK(ID_LINK_CANCEL, FileTransferBar::OnCancel) 
	EVT_HYPERLINK(ID_LINK_REMOVE, FileTransferBar::OnRemove) 

	EVT_HYPERLINK(ID_LINK_OPEN, FileTransferBar::OnOpen) 

END_EVENT_TABLE()


FileTransferBar::FileTransferBar(FileTransferPanel* panel, FileTransferEntry* ftItem)
: wxPanel(panel->scrolledWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER),
	ftPanel(panel)
{

	session = ftItem->GetSession();
	sessionID = ftItem->GetID();
	isSender = ftItem->isSender;
	fileName = ftItem->GetFileName();
	fileSize = ftItem->GetFileSize();

	nameLabel = new wxStaticText(this, wxID_ANY, _T(""));

	wxString tmp = fileName ;
	tmp << _(" (") << NumberUtil::B2KB(fileSize) << _(" KB)");
	nameLabel->SetLabel(tmp);

	progressGauge = new wxGauge(this, -1,100, wxDefaultPosition, wxSize(15, 15));
	progressGauge->SetRange(ftItem->GetFileSize());

	statusLabel = new wxStaticText(this, wxID_ANY, _T(""));

	acceptLink = new wxHyperlinkCtrl(this, ID_LINK_ACCEPT, _("Accept"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);
	saveasLink = new wxHyperlinkCtrl(this, ID_LINK_SAVEAS, _("Save as"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);
	declineLink = new wxHyperlinkCtrl(this, ID_LINK_DECLINE, _("Decline"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);
	cancelLink = new wxHyperlinkCtrl(this, ID_LINK_CANCEL, _("Cancel"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);
	openLink = new wxHyperlinkCtrl(this, ID_LINK_OPEN, _("Open"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);
	removeLink = new wxHyperlinkCtrl(this, ID_LINK_REMOVE, _("Remove"), _T(""), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_ALIGN_CENTRE);

	wxBoxSizer *linkSizer = new wxBoxSizer (wxHORIZONTAL);
	linkSizer->Add( acceptLink, 0, wxALL, 5 );
	linkSizer->Add( saveasLink, 0, wxALL, 5 );
	linkSizer->Add( declineLink, 0, wxALL, 5 );
	linkSizer->Add( cancelLink, 0, wxALL, 5 );
	linkSizer->Add( openLink, 0, wxALL, 5 );
	linkSizer->Add( removeLink, 0, wxALL, 5 );

	wxBoxSizer *fileSizer = new wxBoxSizer (wxVERTICAL);
	fileSizer->Add( nameLabel, 0, wxALL, 0);
	fileSizer->Add( progressGauge, 0, wxTOP|wxBOTTOM|wxEXPAND, 2);
	fileSizer->Add( statusLabel, 0, wxALL, 0);	
	fileSizer->Add( linkSizer, 0, wxALL, 0);

	SetSizer(fileSizer);

	//SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND ));
	//SetBackgroundColour(*wxLIGHT_GREY);
	//SetBackgroundColour(*wxWHITE);
	SetBackgroundColour(wxColour(208,227,232));

	UpdateUIStatus(FT_WAITING);

	
}

FileTransferBar::~FileTransferBar()
{

	DEBUG(_T("~FileTransferBar"));
}

void FileTransferBar::UpdateUIStatus(FileTransferStatus status)
{
	ftStatus = status;

	switch(ftStatus){
		case FT_WAITING:
			if(isSender){
				acceptLink->Hide();
				saveasLink->Hide();
				declineLink->Hide();
				cancelLink->Show();
			}else{
				acceptLink->Show();
				saveasLink->Show();
				declineLink->Show();
				cancelLink->Hide();
			}
			progressGauge->Show();
			openLink->Hide();
			removeLink->Hide();
			statusLabel->SetLabel( _("Waiting"));

			break;
		case FT_ACCEPTING:
			progressGauge->Show();
			cancelLink->Show();
			acceptLink->Hide();
			saveasLink->Hide();
			declineLink->Hide();		
			openLink->Hide();
			removeLink->Hide();
			statusLabel->SetLabel( _("Accepting"));
			break;
		case FT_TRANSFERRING:
			progressGauge->Show();
			cancelLink->Show();
			openLink->Hide();
			removeLink->Hide();
			acceptLink->Hide();
			saveasLink->Hide();
			declineLink->Hide();
			statusLabel->SetLabel(_T(""));
			break;
		case FT_DONE:
			if(isSender){
				openLink->Hide();
				removeLink->Show();		
			}else{
				openLink->Show();
				removeLink->Show();
			}

			progressGauge->Hide();
			cancelLink->Hide();
			acceptLink->Hide();
			saveasLink->Hide();
			declineLink->Hide();
			statusLabel->SetLabel(_("Done"));
			break;
		case FT_CANCELLED:		
			removeLink->Show();
			openLink->Hide();
			progressGauge->Hide();
			cancelLink->Hide();
			acceptLink->Hide();
			saveasLink->Hide();
			declineLink->Hide();
			statusLabel->SetLabel(_("Cancelled"));
			break;
		case FT_FAILED:		
			removeLink->Show();
			openLink->Hide();
			progressGauge->Hide();
			cancelLink->Hide();
			acceptLink->Hide();
			saveasLink->Hide();
			declineLink->Hide();
			statusLabel->SetLabel(_("Failed"));
			break;
	}

	GetSizer()->Layout();
}

void FileTransferBar::CancelFile()
{
/*
	if(ftConnection != NULL){
		ftConnection->Cancel();
		ftConnection->Delete();
	}
*/

	//ftItem->CancelTransfer();

	session->GetFtManager()->CancelTransfer(sessionID);

	UpdateUIStatus(FT_CANCELLED);
	CleanFile();	
}

void FileTransferBar::CleanFile()
{
	if(!isSender){
		FileUtil::DeleteFile(filePath);
	}
}

void FileTransferBar::OnAccept(wxHyperlinkEvent& event)
{
	DEBUG(_T("accept file"));

	FileTransferEntry* ftItem = session->GetFtManager()->GetEntry(sessionID);

	wxString dir = session->GetMessenger()->GetFileTransferDirectory();

	filePath = dir + wxString(wxFileName::GetPathSeparator()) + fileName ;

	ftItem->SetFilePath(filePath);

	session->SendP2PSessionAcceptMessage(ftItem->GetMessage());

	UpdateUIStatus(FT_ACCEPTING);
}

void FileTransferBar::OnSaveas(wxHyperlinkEvent& event)
{
	wxString dir = session->GetMessenger()->GetFileTransferDirectory();
    wxFileDialog fileDialog(this, _("Save file as..."), dir, fileName, _T("*.*"), wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
    if (fileDialog.ShowModal() == wxID_OK){
		FileTransferEntry* ftItem = session->GetFtManager()->GetEntry(sessionID);
		
		filePath = fileDialog.GetPath();
        ftItem->SetFilePath(fileDialog.GetPath());

		session->SendP2PSessionAcceptMessage(ftItem->GetMessage());

		UpdateUIStatus(FT_ACCEPTING);
    }	
}

void FileTransferBar::OnDecline(wxHyperlinkEvent& event)
{
	//ftItem->session->SendFileDeclineMessage(ftItem->cookie);

	FileTransferEntry* ftItem = session->GetFtManager()->GetEntry(sessionID);

	session->SendP2PSessionDeclineMessage(ftItem->GetMessage());

	UpdateUIStatus(FT_CANCELLED);
}

void FileTransferBar::OnOpen(wxHyperlinkEvent& event)
{
	FileUtil::OpenFileWIthDefaultApp(filePath);
}

void FileTransferBar::OnCancel(wxHyperlinkEvent& event)
{
	CancelFile();
}

void FileTransferBar::OnRemove(wxHyperlinkEvent& event)
{
	//remove the entry from panel
	ftPanel->entryMap.erase(sessionID);

	GetParent()->GetSizer()->Detach(this);

	GetParent()->GetSizer()->Layout();
	GetParent()->Refresh();
	Destroy();	
}



BEGIN_EVENT_TABLE(FileTransferPanel, wxPanel)


END_EVENT_TABLE()

FileTransferPanel::FileTransferPanel(wxWindow* parent)
	: wxPanel(parent, wxID_ANY)
{

	scrolledWindow = new wxScrolledWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxHSCROLL);

	scrolledWindow->SetScrollRate( 10, 10 );
    scrolledWindow->SetVirtualSize( 92, 97 );

	fileSizer = new wxBoxSizer (wxVERTICAL);

	scrolledWindow->SetBackgroundColour(*wxWHITE);

	scrolledWindow->SetSizer(fileSizer);

	//scrolledWindow->SetSize(wxSize(400,400));

	wxBoxSizer *sizer = new wxBoxSizer (wxVERTICAL);
	sizer->Add( scrolledWindow, 1, wxALL | wxEXPAND, 1 );

	SetSizer(sizer);
}

FileTransferPanel:: ~FileTransferPanel()
{
	DEBUG(_T("~FileTransferPanel"));
}

void FileTransferPanel::UpdateUIText()
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;
        panel->acceptLink->SetLabel(_("Accept"));
		panel->saveasLink->SetLabel(_("Save as"));
		panel->declineLink->SetLabel(_("Decline"));
		panel->cancelLink->SetLabel(_("Cancel"));
		panel->openLink->SetLabel(_("Open"));
		panel->removeLink->SetLabel(_("Remove"));

		panel->UpdateUIStatus(panel->ftStatus);
    }
}

void FileTransferPanel::AddFileTransfer(FileTransferEntry* item)
{
	FileTransferBar* bar = new FileTransferBar(this, item);

	fileSizer->Insert(0, (wxWindow*)bar, 0, wxLEFT | wxRIGHT | wxEXPAND, 0 );
	fileSizer->InsertSpacer(1, 1);
	fileSizer->Layout();

	scrolledWindow->Refresh();
	scrolledWindow->Update();

	this->Update();

	entryMap[item->GetID()] = bar;
	
}

bool FileTransferPanel::HasLiveItem(MsnSession* session)
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;
        
		if(panel->session == session){
			if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING)
				return true;
		}

    }
	return false;
}

bool FileTransferPanel::HasLiveItemOthers(MsnSession* session)
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;
        
		if(panel->session != session){
			if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING)
				return true;
		}

    }
	return false;
}

bool FileTransferPanel::HasLiveItemAll()
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;
       
		if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING)
			return true;

    }
	return false;
}

void FileTransferPanel::CancelLiveItem(MsnSession* session)
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;      
		
		if(panel->session == session){
			if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING)
				panel->CancelFile();
		}

    }
}

void FileTransferPanel::CancelLiveItemOthers(MsnSession* session)
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;      
		
		if(panel->session != session){
			if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING)
				panel->CancelFile();
		}

    }
}

void FileTransferPanel::CancelLiveItemAll()
{
	for(EntryMap::iterator it = entryMap.begin(); it!= entryMap.end(); ++it){
        FileTransferBar* panel = it->second;
       
		if(panel->ftStatus == FT_WAITING || panel->ftStatus == FT_ACCEPTING || panel->ftStatus == FT_TRANSFERRING){
			panel->CancelFile();
		}

    }	
}


void FileTransferPanel::OnTransferStarted(const wxString& cookie)
{
	FileTransferBar* panel = entryMap[cookie];

	if(panel != NULL){
		//panel->ftConnection = conn;
		panel->UpdateUIStatus(FT_TRANSFERRING);
	}	
}

void FileTransferPanel::OnTransferUpdated(const wxString& cookie, long long value, long speed)
{
	FileTransferBar* panel = entryMap[cookie];

	if(panel != NULL){
		int sum = panel->progressGauge->GetValue() + value;
		panel->progressGauge->SetValue(sum);

		wxString label;
		label << _("Transferred") << _T(": ");
		label << NumberUtil::B2KB(sum) << _T(" KB ");
		label <<  _(" Speed") <<_T(": ");
		label << NumberUtil::B2KB(speed) << _T(" KB/s");

		panel->statusLabel->SetLabel(label);
	}
}

void FileTransferPanel::OnTransferDone(const wxString& cookie)
{
	FileTransferBar* panel = entryMap[cookie];

	if(panel != NULL){	
		panel->progressGauge->SetValue(panel->progressGauge->GetRange());
		panel->UpdateUIStatus(FT_DONE);
	}	
}

void FileTransferPanel::OnTransferFailed(const wxString& cookie)
{
	FileTransferBar* panel = entryMap[cookie];

	if(panel != NULL){
		panel->UpdateUIStatus(FT_FAILED);
		panel->CleanFile();
	}
}

void FileTransferPanel::OnTransferCancelled(const wxString& cookie)
{
	FileTransferBar* panel = entryMap[cookie];

	if(panel != NULL){	
		panel->UpdateUIStatus(FT_CANCELLED);
		panel->CleanFile();
	}	
}


